﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input.Touch;
using System.Threading;
using System.Xml.Linq;
using System.IO.IsolatedStorage;
using System.IO;


namespace GameForKids
{

    public class GamePlayPacMan : DrawableGameComponent
    {
        // bien dem thoi gian
        public float milisecon = 0;
        // hien thi thoi gian choi
        public string timePlay = "";
 
        private SoundEffect correct;
        bool playOneTime = true;
        //kiem tra win
        public bool isWin = false;
        // tao ket noi co so du lieu
        private string strConnectionString = @"isostore:/PacmanDB.sdf";
        SpriteFont font;
        SpriteFont timefont;
        // khai bao gach player va ghost
        List<Brick> listBricks;
        Player player;
        List<Ghost> listGhost;
        // mang cho trong 
        List<Point> listEmptyPoint;
        // mang cac chu co trong du lieu
        string[] listStringLevel1;
        string[] listStringLevel2;
        string[] listStringLevel3;
        string[] listStringLevel4;
        string[] listStringLevel5;
        // chu hien tai chua level
        String stringOfLevel;
        // mang chu dung cho level
        List<string> listStringOfLevel;
        // so chu da choi trong level
        public int numStringPass = 5;
        //chu tiep theo can phai an
        public int currentChar = 0;
        //review string
        public struct CharReView
        {
            public int x;
            public int y;
            public string s;
            public CharReView(int _x, int _y, string _s)
            {
                x = _x;
                y = _y;
                s = _s;
            }
        }
        public List<CharReView> listCharReview;
        // vi tri cua moi chu cai
        public Vector2 positionOfChar;

        public bool configuration = false;
        public int moved = 0;
        public Boolean dacong = false;
        // cong thuc tinh diem

        public static string CongThucGoc = "10-((T-50-50*L)/15)";
        public static string CongThucHienTai = "";

        public GamePlayPacMan(Game game) : base(game)
        {
            // tao csdl
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                if (readAndWriteDB.DatabaseExists() == false)
                {
                    readAndWriteDB.CreateDatabase();
                }
            }
            listBricks = new List<Brick>();
            listGhost = new List<Ghost>();
            listEmptyPoint = new List<Point>();
            listStringOfLevel = new List<string>();
            listCharReview = new List<CharReView>();
            if (GameForKids.language == GameForKids.VIET)
            {
                listStringLevel1 = new string[] { "Sách", "Vở", "Bàn", "Đèn", "Bóng", "Sao", "Bút", "Tàu", "Nước", "Cặp" };
                listStringLevel2 = new string[] { "Thuyền", "Thành phố", "Cô Giáo", "Con mèo", "Xe máy", "Xe đạp", "Đi học" };
                listStringLevel3 = new string[] { "Tàu thuyền", "Nhà sách", "Điện thoại", "Nhà ga", "Từ điển", "Quyển sách" };
                listStringLevel4 = new string[] { "Thông minh", "Chăm chỉ", "Học giỏi", "Chăm ngoan", "Chuyên Cần", "Thiếu nhi" };
                listStringLevel5 = new string[] { "Tàu điện ngầm", "Xe đạp điện", "Ngọn hải đăng", "Nước Việt Nam", "Hồ Chí Minh", "Thủ đô Hà Nội", "Game thiếu nhi" };
            }
            else
            {
                listStringLevel1 = new string[] { "Book", "Chair", "Table", "Lamp", "Ball", "Star", "Pen", "Ship", "Water", "School" };
                listStringLevel2 = new string[] { "Boat", "The city", "Teachers", "The cat", "Motorcycles", "Bicycle", "Learning" };
                listStringLevel3 = new string[] { "Post office", "Bookstore", "Telephone", "Train station", "Dictionary", "Students" };
                listStringLevel4 = new string[] { "Intelligent", "Laborious", "Beautiful", "Sunflowers", "Children", "Water park" };
                listStringLevel5 = new string[] { "Game for kids", "Electric bike", "The lighthouse", "Viet Nam", "Forests", "Dictionary", "Train station" };
            }
            font = game.Content.Load<SpriteFont>("Fonts/pacfont");
            timefont = game.Content.Load<SpriteFont>("Fonts/HelpFont");
            correct = this.Game.Content.Load<SoundEffect>("Sounds/pacmaneat");

            // lay cong thuc
            using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolatedStorageFile.FileExists("CongThuc" + GameForKids.gameState.ToString() + ".txt"))
                {
                    using (IsolatedStorageFileStream isfs = isolatedStorageFile.OpenFile("CongThuc" + GameForKids.gameState.ToString() + ".txt", FileMode.Open))
                    {
                        using (StreamReader reader = new StreamReader(isfs))
                        {
                            while (!reader.EndOfStream)
                            {
                                CongThucHienTai = reader.ReadLine();
                            }
                        }
                    }
                }
            }
            if (CongThucHienTai == "" || CongThucHienTai == null)
                CongThucHienTai = CongThucGoc;
            Initialize();
        }

        public override void Initialize()
        {
            base.Initialize();
        }
        //tinh diem
        public int getScore()
        {
            int mark = 0;
            XuLyCongThuc xulycongthuc;
            string s = "";

            xulycongthuc = new XuLyCongThuc();
            s = xulycongthuc.TinhDiem(CongThucHienTai, moved, (int)(milisecon / 1000), PacManGame.level);
            double d = double.Parse(s);
            mark = (int)d;

            if (mark >= 10)
                return 10;
            if (mark <= 0)
                mark = 0;
            return mark;
        }
        // luu theo dang ID - ten  - level - diem - ngay
        public void saveScore(int _score)
        {
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                DataScore newscore = new DataScore
                {
                    ID = DateTime.Now.ToString(),
                    name = GameForKids.userName,
                    level = PacManGame.level,
                    score = _score,
                    day = DateTime.Today.ToShortDateString()
                };
                readAndWriteDB.TableScore.InsertOnSubmit(newscore);
                readAndWriteDB.SubmitChanges();
            }
        }
        private IList<DataScore> getListDataScore(string _name, int _level)
        {
            IList<DataScore> listDataScore = null;
            using (ReadAndWrite readAndWrite = new ReadAndWrite(strConnectionString))
            {
                IQueryable<DataScore> dataScoreQuery = from data in readAndWrite.TableScore where data.name.Equals(_name) && data.level == _level select data;
                listDataScore = dataScoreQuery.ToList();
            }
            return listDataScore;
        }
        // load mang cac chu moi
        public void reloadListStringOfLevel(int _level)
        {
            listStringOfLevel.Clear();
            switch (_level)
            {
                case 1:
                    for (int i = 0; i < listStringLevel1.Length; i++)
                    {
                        string s = listStringLevel1[i];
                        listStringOfLevel.Add(s);
                    }break;
                case 2:
                    for (int i = 0; i < listStringLevel2.Length; i++)
                    {
                        string s = listStringLevel2[i];
                        listStringOfLevel.Add(s);
                    }break;
                case 3: for (int i = 0; i < listStringLevel3.Length; i++)
                    {
                        string s = listStringLevel3[i];
                        listStringOfLevel.Add(s);
                    } break;
                case 4: for (int i = 0; i < listStringLevel4.Length; i++)
                    {
                        string s = listStringLevel4[i];
                        listStringOfLevel.Add(s);
                    } break;
                case 5: for (int i = 0; i < listStringLevel5.Length; i++)
                    {
                        string s = listStringLevel5[i];
                        listStringOfLevel.Add(s);
                    } break;
            }
        }
        // khoi tao mot man moi
        public void startNewLevel(int _level)
        {
            ChartScreen.listDataScore = this.getListDataScore(GameForKids.userName, PacManGame.level);
            ChartScreen.levelOfGame = _level;
            listEmptyPoint.Clear();
            listBricks.Clear();
            listGhost.Clear();
            listCharReview.Clear();
            currentChar = 0;
            isWin = false;
            LoadTiles("Content/Levels/"+_level.ToString()+".txt");
            positionOfChar = new Vector2(100,2);
            // load mang string
            Random rand = new Random();
            int temp;
            if (numStringPass == 5)
            {
                milisecon = 0;
                moved = 0;
                numStringPass = 1;
                reloadListStringOfLevel(_level);
                temp = rand.Next(0, listStringOfLevel.Count);
                stringOfLevel = listStringOfLevel[temp];
                listStringOfLevel.RemoveAt(temp);
            }
            else
            {
                numStringPass++;
                temp = rand.Next(0, listStringOfLevel.Count);
                stringOfLevel = listStringOfLevel[temp];
                listStringOfLevel.RemoveAt(temp);
            }
            // gan cac chu cai cho mang Ghost
            stringOfLevel = stringOfLevel.Trim();// xoa 2 khoang trang 2 dau neu co
            string tempString = "";
            for (int i = 0; i < stringOfLevel.Length; i++)
            {
                CharReView charreview;
                charreview.x = (int)positionOfChar.X;
                charreview.y = (int)positionOfChar.Y;
                charreview.s = stringOfLevel[i].ToString();
                positionOfChar.X += font.MeasureString(stringOfLevel[i].ToString()).X;
                listCharReview.Add(charreview);
                if(stringOfLevel[i] != ' ' )
                {
                tempString += stringOfLevel[i].ToString();
                temp = rand.Next(0, listEmptyPoint.Count);
                Ghost ghost = new Ghost(this.Game, 
                    new Vector2(listEmptyPoint[temp].X, listEmptyPoint[temp].Y), 
                    stringOfLevel[i].ToString(),rand.Next(0,4)+1);
                listGhost.Add(ghost);
                listEmptyPoint.RemoveAt(temp);
                }
            }
            stringOfLevel = tempString;

        }


        // load cac vat the
        private void LoadTiles(string path)
        {
            int width;
            int height = 0;
            List<string> lines = new List<string>();

            using (StreamReader reader = new StreamReader(TitleContainer.OpenStream(path)))
            {
                string line = reader.ReadLine();
                width = line.Length;
                while (line != null)
                {
                    lines.Add(line);
                    height++;
                    if (line.Length != width)
                        throw new Exception(String.Format("chieu dai cua dong {0} khong dong bo voi cac dong khac", lines.Count));
                    line = reader.ReadLine();
                }
            }

            //load tat ca cac thu trong level
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    char tileType = lines[y][x];
                    LoadTile(tileType, x, y);
                }
            }

        }

        // load tile dua theo ki tu
        public void LoadTile(char tileType, int x, int y)
        {
            switch (tileType)
            {
                case '#': loadBrick(x, y); break;
                case '0': break;
                case 'P': loadPlayer(x, y); break;
                case 'G': loadEmptyPoint(x, y); break;
                default:
                  throw new NotSupportedException(String.Format("Unsupported tile type character '{0}' at position {1}, {2}.", tileType, x, y));
            }
        }
        // load cac cho trong
        public void loadEmptyPoint(int x, int y)
        {
            Point p = new Point(x * 15 + 100, y * 15 + 50);
            listEmptyPoint.Add(p);
        }
        //load player
        public void loadPlayer(int x, int y)
        {
            player = new Player(this.Game, new Vector2(x * 15 + 128, y * 15 + 78));
        }
        //load vien gach
        public void loadBrick(int x, int y)
        {
            Brick b = new Brick(this.Game, new Vector2(x*15+100, y*15+50));
            listBricks.Add(b);
        }
        //draw
        public virtual void Draw(GameTime gametime, SpriteBatch spriteBatch)
        {
            DrawBrick(spriteBatch);
            drawGhost(spriteBatch);
            player.Draw(gametime, spriteBatch);
            if (PacManGame.viewState == PacManGame.ViewState.Playing)
            {
                spriteBatch.DrawString(timefont, timePlay, new Vector2(10, 250), Color.White);
                spriteBatch.DrawString(timefont, moved.ToString(), new Vector2(740, 250), Color.White);
                drawSampleString(spriteBatch);
            }
        }
        //ve chu demo
        public void drawSampleString(SpriteBatch spriteBatch)
        {
            int empty=0;
            for (int i = 0; i < listCharReview.Count;i++ )
            {
                if (listCharReview[i].s.Equals(" "))
                    empty++;
                try
                {

                    spriteBatch.DrawString(
                        font,
                        listCharReview[i].s,
                        new Vector2(listCharReview[i].x, listCharReview[i].y),
                        (listCharReview[i].s.Equals(stringOfLevel[currentChar].ToString()) && i - empty == currentChar) ? Color.Yellow : Color.Black,
                        0.0f,
                        Vector2.Zero,
                        1.0f,
                        SpriteEffects.None,
                        0);
                }
                catch 
                {
                }
            }
        }
        // ve cac con ma
        public void drawGhost(SpriteBatch spriteBatch)
        {
            foreach(Ghost ghost in listGhost)
            ghost.Draw(spriteBatch);
        }

        // ve cac cuc vuong
        private void DrawBrick(SpriteBatch spriteBatch)
        {
            foreach (Brick b in listBricks)
            {
                b.Draw(spriteBatch);
            }

        }
        // kiem tra player voi gach
        public void checkHitBrick()
        {

            foreach (Brick b in listBricks)
            {
                Rectangle playerRect = player.BoundingRectangle();
                Rectangle brickRect = b.BoundingRectangle();
                int x = playerRect.X < brickRect.X ? playerRect.X : brickRect.X;
                int y = playerRect.Y < brickRect.Y ? playerRect.Y : brickRect.Y;
                int x2;
                int y2;
                if ((playerRect.X + playerRect.Width) > (brickRect.X + brickRect.Width))
                    x2 = playerRect.X + playerRect.Width;
                else
                  x2 =   brickRect.X + brickRect.Width;
                if ((playerRect.Y + playerRect.Height) > (brickRect.Y + brickRect.Height))
                    y2 = playerRect.Y + playerRect.Height;
                else
                    y2 = brickRect.Y + brickRect.Height;
                Rectangle borderRect = new Rectangle(x, y, x2 - x, y2 - y);
        
                if (borderRect.Width <= (playerRect.Width + brickRect.Width) && borderRect.Height <= (playerRect.Height + brickRect.Height))
                {
                          if (playerRect.Y > brickRect.Y && playerRect.Y <= (brickRect.Y + brickRect.Height) && player.way == Way.up)
                          {
                              player.canMoveUp = false;
                              player.fixUp();
                          }
                          if (playerRect.Y < brickRect.Y && (playerRect.Y + playerRect.Height) >= brickRect.Y && player.way == Way.down)
                          {
                              player.canMoveDown = false;
                              player.fixDown();
                          }

                        if (playerRect.X < brickRect.X && (playerRect.X + playerRect.Width) >= brickRect.X && player.way == Way.right)
                        {
                            player.canMoveRight = false;
                            player.fixRight();
                        }
                        if (playerRect.X > brickRect.X && playerRect.X <= (brickRect.X + brickRect.Width) && player.way == Way.left)
                        {
                            player.canMoveLeft = false;
                            player.fixLeft();
                        }
                    
                }
            }
            player.resetAlowWay();
        }
        // va cham ghost
        public void checkHitGhost()
        {
            int a = 0;
            for (int i = 0; i < listGhost.Count; i++)
            {
                Rectangle playerRect = player.BoundingRectangle();
                Rectangle ghostRect = listGhost[i].BoundingRectangle();
                int x = playerRect.X < ghostRect.X ? playerRect.X : ghostRect.X;
                int y = playerRect.Y < ghostRect.Y ? playerRect.Y : ghostRect.Y;
                int x2;
                int y2;
                if ((playerRect.X + playerRect.Width) > (ghostRect.X + ghostRect.Width))
                    x2 = playerRect.X + playerRect.Width;
                else
                    x2 = ghostRect.X + ghostRect.Width;
                if ((playerRect.Y + playerRect.Height) > (ghostRect.Y + ghostRect.Height))
                    y2 = playerRect.Y + playerRect.Height;
                else
                    y2 = ghostRect.Y + ghostRect.Height;
                Rectangle borderRect = new Rectangle(x, y, x2 - x, y2 - y);
                
                // neu va cham dung con ma ^^
                if (borderRect.Width <= (playerRect.Width + ghostRect.Width) &&
                    borderRect.Height <= (playerRect.Height + ghostRect.Height))
                {
                    a = 1;
                    if (!dacong && listGhost[i].show)
                    {
                        moved++;
                        dacong = true;
                    }
                    if (listGhost[i].str.Equals(stringOfLevel[currentChar].ToString()) && listGhost[i].show)
                    {
                        if (GameForKids.ISMUSIC && listGhost[i].show)
                        {
                            correct.Play();
                        }
                        if (currentChar < stringOfLevel.Length - 1)
                            currentChar++;
                        listGhost[i].show = false;
                        return;
                    }
                }
               
            }
            if (a == 0)
                dacong = false;
        }
        // hien gio
        public void setTimePlay()
        {
            timePlay = ((int)milisecon / 60000).ToString() + " : " + (((int)milisecon / 1000) % 60).ToString();
        }

        public virtual void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds;
            if (PacManGame.viewState == PacManGame.ViewState.Playing)
            {
                milisecon += elapsed;
                setTimePlay();
            }
            checkHitBrick();
            checkHitGhost();
            player.Update(gameTime);
            updateGhost(gameTime);
            if (checkWin())
            {
                if (GameForKids.ISMUSIC && playOneTime)
                {
                    correct.Play();
                    playOneTime = false;
                }
                if (numStringPass < 5)
                {
                    nextString(elapsed);
                }
                else
                {
                    returnResual(elapsed);
                }
            }
            base.Update(gameTime);
        }
        float timeDelay = 0f;
        //chu ke tiep trong man
        public void nextString(float elapsed)
        {
            timeDelay += elapsed;
            if (timeDelay >= 500)
            {
                timeDelay = 0;
                startNewLevel(PacManGame.level);
            }
        }
        public void returnResual(float elapsed)
        {
            timeDelay += elapsed;
            configuration = true;
            if (timeDelay >= 500)
            {
                configuration = false;
                timeDelay = 0;
                isWin = true;
            }
        }
        //kiem tra win
        public bool checkWin()
        {
            foreach (Ghost g in listGhost)
                if (g.show)
                    return false;
            return true;
        }
        // update con ma
        public void updateGhost(GameTime gameTime)
        {
            foreach(Ghost ghost in listGhost)
            ghost.Update(gameTime);
        }
    }
}
